#!/usr/bin/env python
# -*- coding: utf-8 -*-
#

'''
interface for store module

functions supported :
  * insert
  * update
  * replace
  * erase
  * find

features to support :
  . iterator ???
  . birthtime of data ???


NOTES :
 1. store module do NOT understand data ( sematics, or meaning, or structure ),
    so, if want to store something more than data, such as attributes, some other
    store instance should be envolved
 2. cache module/layer should NOT by-pass; if disable, cache should just pass-through
 3. iterator interface should be CAREFUL

'''

import    os

import    storecache

import    storecell

CACHE_SIZE_DEFAULT = 4194304  # 4MB

class    Store(object) :
    '''
    Store object is charge of a cluster of cells object, and delegate IO operations to them.
    '''
    def    __init__(self, store_path, cb_map, read_cache_size=0, write_cache_size=0) :
        '''
        @param store_path           where data and index stored
        @param cb_map               callback function which map key to cell id
        @param read_cache_size      if cache enabled or not (enable by default)
        @param write_cache_size     if cache enabled or not (enable by default)
        '''
        self.__store_path = store_path
        self.__cb_map_cell = cb_map
        self.__read_cache_size = read_cache_size
        self.__write_cache_size = write_cache_size
        self.__cache = storecache.StoreCache(store_path, read_cache_size, write_cache_size)
        # __init__()

    def     __del__(self) :
        self.__exit()
        # __del__()

    def    insert(self, key, data) :
        '''
        insert or ignore
        '''
        cell_id = self.__getCellID(key)
        self.__cache.insert(cell_id, key, data)
        return self

    def    update(self, key, data)    :
        '''
        update or ignore
        '''
        cell_id = self.__getCellID(key)
        self.__cache.update(cell_id, key, data)
        return self

    def    replace(self, key, data) :
        '''
        update or insert
        '''
        cell_id = self.__getCellID(key)
        self.__cache.replace(cell_id, key, data)
        return self

    def    erase(self, key) :
        '''
        erase
        '''
        cell_id = self.__getCellID(key)
        self.__cache.erase(cell_id, key)
        return self

    def    find(self, key) :
        '''
        find

        return the value on success,
        return None, if no value exists for the key
        raise exception if there are some exceptions during find
        '''
        cell_id = self.__getCellID(key)
        return self.__cache.find(cell_id, key)

    ##
    def setAttr(self, key, name, value) :
        '''
        set attribute for a key
        '''
        cell_id = self.__getCellID(key)
        self.__cache.setAttr(cell_id, key, name, value)

        return  self

    def getAttr(self, key, name) :
        cell_id = self.__getCellID(key)
        return self.__cache.getAttr(cell_id, key, name, value)

    ####################################################################

    def clearCacheStat(self) :
        self.__cache.clearCacheStat()
        # clearCacheStat()

    def statCache(self) :
        return  self.__cache.statCache()
        # statCache()

    ####################################################################

    def __getCellID(self, key) :
        if self.__cb_map_cell :
            return  self.__cb_map_cell(key)

        raise RuntimeError, 'invalid callback to map key to cell ID.'
        # __getCellID()

    def __exit(self) :
        pass
        # __exit()


